//
// Created by test on 23-3-2.
//
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<stdio.h>
#include<iostream>
#include<sys/stat.h>
#include<sys/fcntl.h>
#include<sys/uio.h>
#include<cstdlib>
#define BUF_SIZE 1024
static const char* status_line[2]={"200 OK","500 Internal server error"};
int main(int argc,char* argv[]){
    const char* ip=argv[1];
    int port=atoi(argv[2]);
    const char* file_name=argv[3];
    struct sockaddr_in addr;
    bzero(&addr,sizeof(addr));
    addr.sin_family=AF_INET;
    addr.sin_port=htons(port);
    inet_pton(AF_INET,ip,&addr.sin_addr);
    int sock=socket(PF_INET,SOCK_STREAM,0);
    assert(sock!=-1);
    int ret=bind(sock,(struct sockaddr*)&addr,sizeof(addr));
    assert(ret!=-1);
    ret=listen(sock,5);
    assert(ret!=-1);
    struct sockaddr_in client;
    socklen_t client_len=sizeof(client);
    int connfd=accept(sock,(struct sockaddr*)&client,&client_len);
    assert(connfd!=-1);
    char header_buf[BUF_SIZE];
    memset(header_buf,'\0',BUF_SIZE);
    char* file_buf;
    struct stat file_stat;
    ret=stat(file_name,&file_stat);
    assert(ret!=-1);
    int valid=1;
    int filelen=(int)file_stat.st_size;
    if(S_ISDIR(file_stat.st_mode)){
        valid=0;
    }
    if(file_stat.st_mode&S_IROTH){
       int fd=open(file_name,O_RDONLY);
       file_buf=new char[filelen+1];
       memset(file_buf,'\0',filelen+1);
       if(read(fd,file_buf,filelen<0)){
           valid=0;
       }
    }
    else{
        valid=0;
    }
    int len=0;
    if(valid){
        ret=snprintf(header_buf,BUF_SIZE-1,"%s %s\r\n","HTTP/1.1",status_line[0]);
        len+=ret;
        ret=snprintf(header_buf+len,BUF_SIZE-1-len,"Content-Length: %d\r\n",filelen);
        len+=ret;
        ret=snprintf(header_buf+len,BUF_SIZE-1-len,"%s","\r\n");
        struct iovec iov[2];
        iov[0].iov_base=header_buf;
        iov[0].iov_len=strlen(header_buf);
        iov[1].iov_base=file_buf;
        iov[1].iov_len=file_stat.st_size;
        ret=writev(connfd,iov,2);
        assert(ret!=-1);
    }
    else{
        ret=snprintf(header_buf,BUF_SIZE-1,"%s %s\r\n","HTTP/1.1",status_line[1]);
        len+=ret;
        ret=snprintf(header_buf+len,BUF_SIZE-1-len,"%s","\r\n");
        send(connfd,header_buf,strlen(header_buf),0);
    }
    close(connfd);
    delete [] file_buf;
    close(sock);
    return 0;
}